﻿using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using hentity;
using hutil;

namespace hlog.mongo {
    /**
   *┌────────────────────────────────────────────────┐
   *│　描    述：MongoServer                                                    
   *│　作    者：sgj                                              
   *│　版    本：1.0                                              
   *│　创建时间：2021/6/6 9:58:16                        
   *└────────────────────────────────────────────────┘
   **/
    public class MServer:IMServer  {
         public T show<T>(String _id) {
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection<T>();
            if( collection == null ) {
                return default(T);
            }
            var query = Query.EQ("_id" ,new ObjectId(_id));
            T logger = collection.FindOneAs<T>(query);
            return logger;
        }

        public BsonDocument show(string name ,string _id) {
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection (name);
            if( collection == null ) {
                return null;
            }
            var query = Query.EQ("_id" ,new ObjectId(_id));
            BsonDocument logger = collection.FindOne (query);
            return logger;
        }
        public void save<T>(T t) where T : BaseMongoLog {
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection<T>();
            if( collection != null ) {
                collection.Insert(t);
            }
       
           
        }
        public void InsertBatch<T>(List<T> log ) where T : BaseMongoLog {

 
            if( log.Count > 0 ) {
                Type t = log[0].GetType();
                MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection(t);
                if( collection == null ) {
                    return ;
                }
                collection.InsertBatch(log);
            }
         }

        public void InsertBatch(string className ,List<object> log)  {
            string name = HUtil.camelCase2_(className);
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection(name);
            if( collection == null ) {
                return;
            }
            if( log.Count > 0 ) {
                collection.InsertBatch(log);
            }
        }

        public void InsertBatch(string className ,List<BsonDocument> defList) {
            string name = HUtil.camelCase2_(className);
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection(name);
            if( collection == null ) {
                return;
            }
            if( defList.Count == 0 ) {
                return;
            }
            foreach( BsonDocument document in defList ) {
                document.Add("_id" ,HUtil.to64());
            }
            collection.InsertBatch(defList);
       
        }
        public Page<Object> queryPage(String name ,int begin  ,List<IMongoQuery> queryList) {
            int limit = 100;
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection(name);
            if( collection == null ) {
                return null;
            }
            Page<Object> page = new Page<Object>();
            SortByBuilder b = new SortByBuilder();
            b.Descending( "_id");
            MongoCursor<BsonDocument> result;
            if( queryList.Count > 0 ) {
                var query = Query.And(queryList);
                result = collection.Find(query).SetSkip(begin).SetLimit(limit).SetSortOrder(b);
                page.totalSize = collection.Count(query);
            } else {
                result = collection.FindAll().SetSkip(begin).SetLimit(limit).SetSortOrder(b);
                page.totalSize = collection.Count();
            }
            List<Object> logList = new List<Object>();
            foreach( BsonDocument log in result ) {
                logList.Add(ObjectUtil.toOb(log));
            }
            page.content = logList;
            return page;
        }

        public Page<Object> queryPage(String name,MongoPageDto param) {

            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection(name);
            if( collection == null ) {
                return null;
            }
            Res res = queryPage(collection ,param);
            Page<Object> page = new Page<Object>();
            

            List<Object> logList = new List<Object>();
            foreach( BsonDocument log in res.result ) {
                logList.Add(ObjectUtil.toOb(log));
            }
            page.content = logList;
            page.totalSize = res.totalSize;
            return page;
        }



        public Page<T> queryPage<T>(MongoPageDto dto) {
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection<T>();
            if( collection == null ) {
                return null;
            }
            Res res = queryPage(collection ,dto);
            Page<T> page = new Page<T>();
            List<T> logList = new List<T>();
            foreach( BsonDocument log in res.result ) {
                T t = BsonSerializer.Deserialize<T>(log);
                logList.Add(t);
            }
            page.content = logList;
            page.totalSize = res.totalSize;
            return page;
        }

        class Res {
            public long totalSize;
            public MongoCursor<BsonDocument> result;
        }
        private Res queryPage(MongoCollection<BsonDocument> collection ,MongoPageDto dto) {
            int begin = (dto.pageNum - 1) * dto.pageSize;
            int limit = dto.pageSize;
            List<IMongoQuery> queryList = dto.getRestrict();
            Res res = new Res();
            SortByBuilder b = dto.getOrder();
            if( queryList.Count > 0 ) {
                var query = Query.And(queryList);
                res.result = collection.Find(query).SetSkip(begin).SetLimit(limit).SetSortOrder(b);
                res.totalSize = collection.Count(query);
            } else {
                res.result = collection.FindAll().SetSkip(begin).SetLimit(limit).SetSortOrder(b);
                res.totalSize = collection.Count();
            }
            return res;
        }


        public  void backUp(Object t ,bool force = false) {
            if( t == null ) {
                return;
            }
            Type type = t.GetType();
            MongoCollection collection = ConnectionCache.getMongoCollection(type);
            if( collection == null ) {
                return ;
            }
            if( collection.Count(Query.EQ("id" ,( long ) HUtil.getValue(t ,"id"))) > 0 && !force ) {
                return;
            }
            var document = BsonDocument.Parse(HUtil.mySerializeObject(t));
            document.Add("_id" ,HUtil.to64());
            Dictionary<string ,DateTime> res = HUtil.getDate(t);
            foreach( var f in res ) {
                document[f.Key] = f.Value;
            }
            collection.Insert(document);
        }

        public void deleteCollection<T>(IMongoQuery query) {
            MongoCollection collection = ConnectionCache.getMongoCollection<T>();
            if( collection == null ) {
                return ;
            }
            collection.Remove(query);
        }


        public List<BsonDocument> queryAll(string className ,IMongoQuery query ,SortByBuilder builder) {
            string name = HUtil.camelCase2_(className);
            MongoCollection<BsonDocument> collection = ConnectionCache.getMongoCollection(name);
            if( collection == null ) {
                return null;
            }
            List<BsonDocument> result = null;
            if( query == null && builder == null ) {
                result = collection.FindAll().ToList();
            } else
            if( query != null && builder == null ) {
                result = collection.Find(query).ToList();
            } else
            if( query == null && builder != null ) {
                result = collection.FindAll().SetSortOrder(builder).ToList();
            } else {
                result = collection.Find(query).SetSortOrder(builder).ToList();
            }
    

            
            return result;
        }

    }
}
